home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 June: Reference Library / Dev.CD Jun 00 RL Disk 1.toast / pc / technical documentation / develop / develop issue 26 / develop issue 26 code / qd3d custom attributes / customattribute / customattribute_lib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-01  |  32.8 KB  |  1,567 lines

  1. /*
  2.  * CustomIO_Lib.c
  3.  *
  4.  *    Demo/Template for writing custom IO functions
  5.  *    
  6.  *    Custom Attribute example
  7.  */
  8. #include <QD3D.h>
  9. #include <QD3DSet.h>
  10.  
  11. #include <QD3DIO.h>
  12. #include <QD3DString.h>
  13. #include <QD3DGeometry.h>
  14. #include <QD3DGroup.h>
  15.  
  16. #include <stdlib.h>
  17.  
  18. #include "CustomAttribute_Lib.h"
  19.  
  20. /*
  21.  *    This file contains the implementation for the following custom attributes
  22.  *    
  23.  *    name - contains a string object, can be attached to any object below shape
  24.  *    scle - scale, determines the relative scale of an object/group with 1 meter
  25.  *    upvt - up vector, determines the vertical orientation of an object/group
  26.  *    fwvt - forward vector, determines the front orientation of an object/group
  27.  *    url     - allows you to attach an URL to an object/group
  28.  */
  29.  
  30. /*
  31.  * Globals
  32.  */
  33. static TQ3ObjectClass    gNameAttributeClass = NULL,
  34.                         gScaleAttributeClass = NULL,
  35.                         gUpVectorAttributeClass = NULL,
  36.                         gForwardVectorAttributeClass = NULL,
  37.                         gW3AnchorClass = NULL,
  38.                         gW3InlineClass = NULL,
  39.                         gWWWAnchorClass = NULL;
  40.  
  41.  
  42. /*
  43.  *    These are the registration calls for the individual attributes
  44.  */
  45. TQ3Status NameAttribute_Register( void);
  46.  
  47. TQ3Status NameAttribute_Unregister( void);
  48.  
  49. TQ3Status ScaleAttribute_Register( void);
  50.     
  51. TQ3Status ScaleAttribute_Unregister( void);
  52.  
  53. TQ3Status UpVectorAttribute_Register( void);
  54.  
  55. TQ3Status UpVectorAttribute_Unregister( void);
  56.  
  57. TQ3Status ForwardDirectionAttribute_Register( void);
  58.  
  59. TQ3Status ForwardDirectionAttribute_Unregister( void);
  60.  
  61. TQ3Status W3Anchor_Register( void);
  62.  
  63. TQ3Status W3Anchor_UnRegister( void);
  64.  
  65. TQ3Status W3Anchor_Unregister( void);
  66.  
  67. TQ3Status W3Inline_Register( void);
  68.  
  69. TQ3Status W3Inline_Unregister( void);
  70.  
  71. TQ3Status WWWAnchor_Register( void );
  72.  
  73. TQ3Status WWWAnchor_Unregister( void);
  74.  
  75. /**********************************************************************************************
  76.  *
  77.  *                        PUBLIC ROUTINES FOR REGISTRATION AND UNREGISTRATION
  78.  *
  79.  **********************************************************************************************/
  80.  
  81. void RegisterAllCustomAttributes(void)
  82. {
  83.     NameAttribute_Register();
  84.  
  85.     ScaleAttribute_Register();
  86.     
  87.     UpVectorAttribute_Register();
  88.  
  89.     ForwardDirectionAttribute_Register();
  90.  
  91.     W3Anchor_Register();
  92.  
  93.     W3Inline_Register();
  94.  
  95.     WWWAnchor_Register();
  96. }
  97.  
  98.  
  99. void UnregisterAllCustomAttributes(void)
  100. {
  101.     NameAttribute_Unregister();
  102.  
  103.     ScaleAttribute_Unregister();
  104.     
  105.     UpVectorAttribute_Unregister();
  106.  
  107.     ForwardDirectionAttribute_Unregister();
  108.  
  109.     W3Anchor_Unregister();
  110.  
  111.     W3Inline_Unregister();
  112.  
  113.     WWWAnchor_Unregister();
  114. }
  115.  
  116. /**********************************************************************************************
  117.  *
  118.  *                                        NAME custom attribute
  119.  *
  120.  **********************************************************************************************/
  121.  
  122.  
  123. /*
  124.  * Utility function to add a name on an shape object, geometry object, or attribute set
  125.  */
  126.  
  127. TQ3Status    SetName(TQ3Object object, char    *name)
  128. {
  129.     TQ3StringObject    string = NULL;
  130.     TQ3AttributeSet    set = NULL;
  131.     TQ3Status        status = kQ3Success;
  132.     
  133.     if( Q3Object_IsType(object, kQ3SharedTypeShape) == kQ3True ) {
  134.         
  135.         string = Q3CString_New(name);
  136.         
  137.         if( string == NULL) {
  138.             status = kQ3Failure;
  139.             goto cleanExit;
  140.         }
  141.             
  142.         if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  143.             
  144.             Q3Geometry_GetAttributeSet(object, &set);
  145.             
  146.             if( set == NULL ) {
  147.                 set = Q3AttributeSet_New();
  148.                 if( set == NULL ) {
  149.                     status = kQ3Failure;
  150.                     goto cleanExit;
  151.                 }
  152.                 Q3Geometry_SetAttributeSet(object, set);
  153.             }
  154.         } else {
  155.             Q3Shape_GetSet(object, &set);
  156.             
  157.             if( set == NULL ) {
  158.                 set = Q3Set_New();
  159.                 if( set == NULL ) {
  160.                     status = kQ3Failure;
  161.                     goto cleanExit;
  162.                 }
  163.                 Q3Shape_SetSet(object, set);
  164.             }
  165.         }
  166.             
  167.         if( Q3Set_Add(set, kElementTypeName, &string) == kQ3Failure ) {
  168.             status = kQ3Failure;
  169.             goto cleanExit;
  170.         }
  171.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  172.         string = Q3CString_New(name);
  173.         
  174.         if( string == NULL) {
  175.             status = kQ3Failure;
  176.             goto cleanExit;
  177.         }
  178.         
  179.         if( Q3AttributeSet_Add(object, kElementTypeName, &string) == kQ3Failure ) {
  180.             status = kQ3Failure;
  181.             goto cleanExit;
  182.         }
  183.     } else 
  184.         status = kQ3Failure;
  185.         
  186. cleanExit:
  187.     if( string )
  188.         Q3Object_Dispose(string);
  189.     if( set )
  190.         Q3Object_Dispose(set);
  191.     return status;
  192. }
  193.  
  194. /*
  195.  * Static Functions
  196.  */
  197.  
  198. static TQ3Status NameAttribute_Traverse(
  199.     TQ3Object                unused,
  200.     TQ3StringObject            *stringObject,
  201.     TQ3ViewObject            view)
  202. {
  203.     (void) unused;
  204.     
  205.     if (stringObject == NULL || *stringObject == NULL)
  206.         return kQ3Success;
  207.  
  208.     Q3View_SubmitWriteData(view,0,0,0);
  209.  
  210.     if (Q3Object_Submit( *stringObject, view) == kQ3Failure)
  211.         return kQ3Failure;
  212.  
  213.     return kQ3Success;
  214. }
  215.  
  216. static TQ3Status NameAttribute_ReadData(
  217.     TQ3SetObject            attributeSet,
  218.     TQ3FileObject            file)
  219. {
  220.     TQ3StringObject        stringObject;
  221.     TQ3Status            status;
  222.     
  223.     stringObject = Q3File_ReadObject(file);
  224.         
  225.     status = Q3Set_Add(attributeSet, kElementTypeName, &stringObject);
  226.     
  227.     Q3Object_Dispose(stringObject);
  228.  
  229.     /*
  230.         Note that the string object has a reference count of 1,
  231.         which will be taken care of in the dispose
  232.     */
  233.     return status;
  234. }
  235.  
  236. static TQ3Status NameAttribute_CopyAdd(
  237.     TQ3StringObject    *src,
  238.     TQ3StringObject    *dst)
  239. {
  240.     *dst = Q3Shared_GetReference(*src);
  241.     if (*dst == NULL) 
  242.         return kQ3Failure;
  243.     
  244.     return kQ3Success;
  245. }
  246.  
  247. static TQ3Status NameAttribute_CopyReplace(
  248.     TQ3StringObject    *src,
  249.     TQ3StringObject    *dst)
  250. {
  251.     TQ3StringObject    tempString;
  252.     
  253.     /*
  254.         It is always good form to get a reference first,
  255.         in case src and dst point to the same object
  256.     */
  257.     
  258.     tempString = Q3Shared_GetReference(*src);
  259.     if (tempString == NULL) 
  260.         return kQ3Failure;
  261.  
  262.     if( *src )
  263.         Q3Object_Dispose( *src );
  264.     
  265.     *dst = tempString;
  266.  
  267.     return kQ3Success;
  268. }
  269.  
  270. static TQ3Status NameAttribute_Delete(
  271.     TQ3StringObject    *stringObject)
  272. {
  273.     if(*stringObject)
  274.         Q3Object_Dispose(*stringObject);
  275.     return kQ3Success;
  276. }
  277.  
  278. TQ3Status NameAttribute_Unregister(
  279.     void)
  280. {
  281.     if ( gNameAttributeClass != NULL )
  282.         return    Q3ObjectClass_Unregister(gNameAttributeClass);
  283.         
  284.     return kQ3Failure;
  285. }
  286.  
  287. /*
  288.  * NameAttribute_MetaHandler
  289.  */
  290. static TQ3FunctionPointer NameAttribute_MetaHandler(
  291.     TQ3MethodType        methodType)
  292. {
  293.     switch (methodType)
  294.     {
  295.         case kQ3MethodTypeObjectTraverse:
  296.             return (TQ3FunctionPointer) NameAttribute_Traverse;
  297.         case kQ3MethodTypeObjectReadData:
  298.             return (TQ3FunctionPointer) NameAttribute_ReadData;
  299.         case kQ3MethodTypeElementCopyAdd:
  300.         case kQ3MethodTypeElementCopyGet:
  301.         case kQ3MethodTypeElementCopyDuplicate:
  302.             return (TQ3FunctionPointer) NameAttribute_CopyAdd;
  303.         case kQ3MethodTypeElementCopyReplace:
  304.             return (TQ3FunctionPointer) NameAttribute_CopyReplace;
  305.         case kQ3MethodTypeElementDelete:
  306.             return (TQ3FunctionPointer) NameAttribute_Delete;
  307.         default:
  308.             return (TQ3FunctionPointer) NULL;
  309.     }
  310. }
  311.  
  312. /*
  313.  * NameAttribute_Register
  314.  */
  315. TQ3Status NameAttribute_Register(
  316.     void)
  317. {
  318.     gNameAttributeClass = 
  319.         Q3ElementClass_Register(
  320.             kElementTypeName,
  321.             "NameAttribute",
  322.             sizeof(TQ3StringObject),
  323.             NameAttribute_MetaHandler);
  324.  
  325.     return (gNameAttributeClass == NULL ? kQ3Failure : kQ3Success);
  326. }
  327.  
  328. /**********************************************************************************************
  329.  *
  330.  *                                        SCALE custom attribute
  331.  *
  332.  **********************************************************************************************/
  333.  
  334. /*
  335.  * Utility function to add a scale on an shape object, geometry object, or attribute set
  336.  */
  337.  
  338. TQ3Status    SetScale(TQ3Object object, double scale)
  339. {
  340.     TQ3AttributeSet    set = NULL;
  341.     TQ3Status        status = kQ3Success;
  342.     
  343.     if( Q3Object_IsType(object, kQ3SharedTypeShape) == kQ3True ) {
  344.         
  345.         if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  346.             
  347.             Q3Geometry_GetAttributeSet(object, &set);
  348.             
  349.             if( set == NULL ) {
  350.                 set = Q3AttributeSet_New();
  351.                 if( set == NULL ) {
  352.                     status = kQ3Failure;
  353.                     goto cleanExit;
  354.                 }
  355.                 Q3Geometry_SetAttributeSet(object, set);
  356.             }
  357.         } else {
  358.             Q3Shape_GetSet(object, &set);
  359.             
  360.             if( set == NULL ) {
  361.                 set = Q3Set_New();
  362.                 if( set == NULL ) {
  363.                     status = kQ3Failure;
  364.                     goto cleanExit;
  365.                 }
  366.                 Q3Shape_SetSet(object, set);
  367.             }
  368.         }
  369.             
  370.         if( Q3Set_Add(set, kElementTypeScale, &scale) == kQ3Failure ) {
  371.             status = kQ3Failure;
  372.             goto cleanExit;
  373.         }
  374.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  375.         if( Q3AttributeSet_Add(object, kElementTypeScale, &scale) == kQ3Failure ) {
  376.             status = kQ3Failure;
  377.             goto cleanExit;
  378.         }
  379.     } else 
  380.         status = kQ3Failure;
  381.         
  382. cleanExit:
  383.     if( set )
  384.         Q3Object_Dispose(set);
  385.     return status;
  386. }
  387.  
  388. /*
  389.  * ScaleAttribute_Traverse
  390.  */
  391.  
  392. static TQ3Status ScaleAttribute_Traverse(
  393.     TQ3Object                unused,
  394.     TQ3Float64                *scale,
  395.     TQ3ViewObject            view)
  396. {
  397.     (void) unused;
  398.     
  399.     if (scale == NULL)
  400.         return kQ3Success;
  401.  
  402.     return Q3View_SubmitWriteData(
  403.         view, sizeof(TQ3Float64), scale, NULL);
  404. }
  405.  
  406. /*
  407.  * ScaleAttribute_Write
  408.  */
  409.  
  410. static TQ3Status ScaleAttribute_Write(
  411.     TQ3Float64                *scale,
  412.     TQ3FileObject            file)
  413. {
  414.     return 
  415.         Q3Float64_Write(*scale, file);
  416. }
  417.  
  418. /*
  419.  * ScaleAttribute_ReadData
  420.  */
  421.  
  422. static TQ3Status ScaleAttribute_ReadData(
  423.     TQ3SetObject            attributeSet,
  424.     TQ3FileObject            file)
  425. {
  426.     double            scale;
  427.     
  428.     if( Q3Float64_Read(&scale, file) == kQ3Failure) {
  429.         return kQ3Failure;
  430.     }
  431.         
  432.     return Q3Set_Add(attributeSet, kElementTypeScale, &scale);
  433. }
  434.  
  435. /*
  436.  * ScaleAttribute_MetaHandler
  437.  */
  438. static TQ3FunctionPointer ScaleAttribute_MetaHandler(
  439.     TQ3MethodType        methodType)
  440. {
  441.     switch (methodType)
  442.     {
  443.         case kQ3MethodTypeObjectTraverse:
  444.             return (TQ3FunctionPointer) ScaleAttribute_Traverse;
  445.         case kQ3MethodTypeObjectWrite:
  446.             return (TQ3FunctionPointer) ScaleAttribute_Write;
  447.         case kQ3MethodTypeObjectReadData:
  448.             return (TQ3FunctionPointer) ScaleAttribute_ReadData;
  449.         default:
  450.             return (TQ3FunctionPointer) NULL;
  451.     }
  452. }
  453.  
  454. /*
  455.  * ScaleAttribute_Register
  456.  */
  457. TQ3Status ScaleAttribute_Register(
  458.     void)
  459. {
  460.     gScaleAttributeClass = 
  461.         Q3ElementClass_Register(
  462.             kElementTypeScale,
  463.             "ScaleAttribute",
  464.             sizeof(TQ3Float64),
  465.             ScaleAttribute_MetaHandler);
  466.  
  467.     return (gScaleAttributeClass == NULL ? kQ3Failure : kQ3Success);
  468. }
  469.  
  470. /*
  471.  * ScaleAttribute_Unregister
  472.  */
  473. TQ3Status ScaleAttribute_Unregister(
  474.     void)
  475. {
  476.     if ( gScaleAttributeClass != NULL )
  477.         return    Q3ObjectClass_Unregister(gScaleAttributeClass);
  478.         
  479.     return kQ3Failure;
  480. }
  481.  
  482. /**********************************************************************************************
  483.  *
  484.  *                                common routines for dealing with vectors
  485.  *
  486.  **********************************************************************************************/
  487.  
  488. static TQ3Status vector_Traverse(
  489.     TQ3Object                unused,
  490.     TQ3Vector3D                *upVector,
  491.     TQ3ViewObject            view)
  492. {
  493.     (void) unused;
  494.     
  495.     if (upVector == NULL)
  496.         return kQ3Success;
  497.  
  498.     return Q3View_SubmitWriteData(
  499.         view, sizeof(TQ3Vector3D), upVector, NULL);
  500. }
  501.  
  502. static TQ3Status vector_Write(
  503.     TQ3Vector3D                *upVector,
  504.     TQ3FileObject            file)
  505. {
  506.     return 
  507.         Q3Vector3D_Write(upVector, file);
  508. }
  509.  
  510. static TQ3Status vector_CopyAdd(
  511.     TQ3Vector3D    *src,
  512.     TQ3Vector3D    *dst)
  513. {
  514.     *dst = *src;
  515.     return kQ3Success;
  516. }
  517.  
  518. static TQ3Status vector_CopyReplace(
  519.     TQ3Vector3D    *src,
  520.     TQ3Vector3D    *dst)
  521. {
  522.     *dst = *src;
  523.     return kQ3Success;
  524. }
  525.  
  526. /**********************************************************************************************
  527.  *
  528.  *                                        UP VECTOR custom attribute
  529.  *
  530.  **********************************************************************************************/
  531.  
  532. /*
  533.  * Utility function to specify the up vector on a group, geometry object, or attribute set
  534.  */
  535.  
  536. TQ3Status    SetUpVector(TQ3Object object, TQ3Vector3D *upVector)
  537. {
  538.     TQ3AttributeSet    set = NULL;
  539.     TQ3Status        status = kQ3Success;
  540.     
  541.     if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  542.         Q3Geometry_GetAttributeSet(object, &set);
  543.         
  544.         if( set == NULL ) {
  545.             set = Q3AttributeSet_New();
  546.             if( set == NULL ) {
  547.                 status = kQ3Failure;
  548.                 goto cleanExit;
  549.             }
  550.             Q3Geometry_SetAttributeSet(object, set);
  551.         }
  552.     } else if( Q3Object_IsType(object, kQ3ShapeTypeGroup) == kQ3True ){
  553.         Q3Shape_GetSet(object, &set);
  554.         
  555.         if( set == NULL ) {
  556.             set = Q3Set_New();
  557.             if( set == NULL ) {
  558.                 status = kQ3Failure;
  559.                 goto cleanExit;
  560.             }
  561.             Q3Shape_SetSet(object, set);
  562.         }
  563.     }
  564.             
  565.     if( set ) {
  566.         if( Q3Set_Add(set, kElementTypeUpVector, &upVector) == kQ3Failure ) {
  567.             status = kQ3Failure;
  568.             goto cleanExit;
  569.         }
  570.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  571.         if( Q3AttributeSet_Add(object, kElementTypeUpVector, &upVector) == kQ3Failure ) {
  572.             status = kQ3Failure;
  573.             goto cleanExit;
  574.         }
  575.     } else 
  576.         status = kQ3Failure;
  577.         
  578. cleanExit:
  579.     if( set )
  580.         Q3Object_Dispose(set);
  581.     return status;
  582. }
  583.  
  584. /*
  585.  * UpVectorAttribute_ReadData
  586.  */
  587. static TQ3Status UpVectorAttribute_ReadData(
  588.     TQ3SetObject            attributeSet,
  589.     TQ3FileObject            file)
  590. {
  591.     TQ3Vector3D        upVector;
  592.     
  593.     if( Q3Vector3D_Read(&upVector, file) == kQ3Failure) {
  594.         return kQ3Failure;
  595.     }
  596.         
  597.     return Q3Set_Add(attributeSet, kElementTypeUpVector, &upVector);
  598. }
  599.  
  600. /*
  601.  * UpVectorAttribute_MetaHandler
  602.  */
  603. static TQ3FunctionPointer UpVectorAttribute_MetaHandler(
  604.     TQ3MethodType        methodType)
  605. {
  606.     switch (methodType)
  607.     {
  608.         case kQ3MethodTypeObjectTraverse:
  609.             return (TQ3FunctionPointer) vector_Traverse;
  610.         case kQ3MethodTypeObjectWrite:
  611.             return (TQ3FunctionPointer) vector_Write;
  612.         case kQ3MethodTypeObjectReadData:
  613.             return (TQ3FunctionPointer) UpVectorAttribute_ReadData;
  614.         case kQ3MethodTypeElementCopyAdd:
  615.         case kQ3MethodTypeElementCopyGet:
  616.         case kQ3MethodTypeElementCopyDuplicate:
  617.             return (TQ3FunctionPointer) vector_CopyAdd;
  618.         case kQ3MethodTypeElementCopyReplace:
  619.             return (TQ3FunctionPointer) vector_CopyReplace;
  620.         default:
  621.             return (TQ3FunctionPointer) NULL;
  622.     }
  623. }
  624.  
  625. /*
  626.  * UpVectorAttribute_Register
  627.  */
  628. TQ3Status UpVectorAttribute_Register(
  629.     void)
  630. {
  631.     gUpVectorAttributeClass = 
  632.         Q3ElementClass_Register(
  633.             kElementTypeUpVector,
  634.             "UpVector",
  635.             sizeof(TQ3Vector3D),
  636.             UpVectorAttribute_MetaHandler);
  637.  
  638.     return (gUpVectorAttributeClass == NULL ? kQ3Failure : kQ3Success);
  639. }
  640.  
  641. /*
  642.  * UpVectorAttribute_Unregister
  643.  */
  644. TQ3Status UpVectorAttribute_Unregister(
  645.     void)
  646. {
  647.     if ( gUpVectorAttributeClass != NULL )
  648.         return    Q3ObjectClass_Unregister(gUpVectorAttributeClass);
  649.         
  650.     return kQ3Failure;
  651. }
  652.  
  653. /**********************************************************************************************
  654.  *
  655.  *                                FORWARD DIRECTION custom attribute
  656.  *
  657.  **********************************************************************************************/
  658. /*
  659.  * Utility function to add a name on a group, geometry object, or attribute set
  660.  */
  661.  
  662. TQ3Status    SetForwardDirection(TQ3Object object, TQ3Vector3D *forwardDirection)
  663. {
  664.     TQ3AttributeSet    set = NULL;
  665.     TQ3Status        status = kQ3Success;
  666.     
  667.     if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  668.         Q3Geometry_GetAttributeSet(object, &set);
  669.         
  670.         if( set == NULL ) {
  671.             set = Q3AttributeSet_New();
  672.             if( set == NULL ) {
  673.                 status = kQ3Failure;
  674.                 goto cleanExit;
  675.             }
  676.             Q3Geometry_SetAttributeSet(object, set);
  677.         }
  678.     } else if( Q3Object_IsType(object, kQ3ShapeTypeGroup) == kQ3True ){
  679.         Q3Shape_GetSet(object, &set);
  680.         
  681.         if( set == NULL ) {
  682.             set = Q3Set_New();
  683.             if( set == NULL ) {
  684.                 status = kQ3Failure;
  685.                 goto cleanExit;
  686.             }
  687.             Q3Shape_SetSet(object, set);
  688.         }
  689.     }
  690.             
  691.     if( set ) {
  692.         if( Q3Set_Add(set, kElementTypeForwardDirection, &forwardDirection) == kQ3Failure ) {
  693.             status = kQ3Failure;
  694.             goto cleanExit;
  695.         }
  696.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  697.         if( Q3AttributeSet_Add(object, kElementTypeForwardDirection, &forwardDirection) == kQ3Failure ) {
  698.             status = kQ3Failure;
  699.             goto cleanExit;
  700.         }
  701.     } else 
  702.         status = kQ3Failure;
  703.         
  704. cleanExit:
  705.     if( set )
  706.         Q3Object_Dispose(set);
  707.     return status;
  708. }            
  709.  
  710. /*
  711.  * ForwardDirectionAttribute_ReadData
  712.  */
  713. static TQ3Status ForwardDirectionAttribute_ReadData(
  714.     TQ3SetObject            attributeSet,
  715.     TQ3FileObject            file)
  716. {
  717.     TQ3Vector3D        forwardDirection;
  718.     
  719.     if( Q3Vector3D_Read(&forwardDirection, file) == kQ3Failure) {
  720.         return kQ3Failure;
  721.     }
  722.         
  723.     return Q3Set_Add(attributeSet, kElementTypeForwardDirection, &forwardDirection);
  724. }
  725.  
  726. /*
  727.  * ForwardDirectionAttribute_MetaHandler
  728.  */
  729. static TQ3FunctionPointer ForwardDirectionAttribute_MetaHandler(
  730.     TQ3MethodType        methodType)
  731. {
  732.     switch (methodType)
  733.     {
  734.         case kQ3MethodTypeObjectTraverse:
  735.             return (TQ3FunctionPointer) vector_Traverse;
  736.         case kQ3MethodTypeObjectWrite:
  737.             return (TQ3FunctionPointer) vector_Write;
  738.         case kQ3MethodTypeObjectReadData:
  739.             return (TQ3FunctionPointer) ForwardDirectionAttribute_ReadData;
  740.         default:
  741.             return (TQ3FunctionPointer) NULL;
  742.     }
  743. }
  744.  
  745. /*
  746.  * ForwardDirectionAttribute_Register
  747.  */
  748. TQ3Status ForwardDirectionAttribute_Register(
  749.     void)
  750. {
  751.     gUpVectorAttributeClass = 
  752.         Q3ElementClass_Register(
  753.             kElementTypeForwardDirection,
  754.             "ForwardDirection",
  755.             sizeof(TQ3Vector3D),
  756.             ForwardDirectionAttribute_MetaHandler);
  757.  
  758.     return (gForwardVectorAttributeClass == NULL ? kQ3Failure : kQ3Success);
  759. }
  760.  
  761. /*
  762.  * ForwardDirectionAttribute_Unregister
  763.  */
  764. TQ3Status ForwardDirectionAttribute_Unregister(
  765.     void)
  766. {
  767.     if ( gForwardVectorAttributeClass != NULL )
  768.         return    Q3ObjectClass_Unregister(gForwardVectorAttributeClass);
  769.         
  770.     return kQ3Failure;
  771. }
  772.  
  773. /***********************************************************************************************
  774. *
  775. *    W3Anchor - This allows you attach an URL (universal resource locator) to an object or
  776. *    group.  If this attribute is attached to a group, it should be interpreted as applying
  777. *    to all the objects inside the group.
  778. *
  779. *
  780. ***********************************************************************************************/
  781.  
  782. /*
  783.  * Utility function to attach an URL reference to a group object, geometry object, or attribute set
  784.  */
  785.  
  786. TQ3Status    SetW3Anchor(TQ3Object object, char *url, char *description, W3AnchorOptions options)
  787. {
  788.     TQ3StringObject        string = NULL;
  789.     TQ3AttributeSet        set = NULL;
  790.     TQ3Status            status = kQ3Success;
  791.     W3AnchorData        W3Anchor;
  792.         
  793.     string = Q3CString_New(description);
  794.     
  795.     if( string == NULL) {
  796.         status = kQ3Failure;
  797.         goto cleanExit;
  798.     }
  799.     
  800.     W3Anchor.description = string;
  801.     W3Anchor.url = url;
  802.     W3Anchor.options = options;
  803.     
  804.     if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  805.         
  806.         Q3Geometry_GetAttributeSet(object, &set);
  807.         
  808.         if( set == NULL ) {
  809.             set = Q3AttributeSet_New();
  810.             if( set == NULL ) {
  811.                 status = kQ3Failure;
  812.                 goto cleanExit;
  813.             }
  814.             Q3Geometry_SetAttributeSet(object, set);
  815.         }
  816.     } else if( Q3Object_IsType(object, kQ3ShapeTypeGroup) == kQ3True ) {
  817.         Q3Shape_GetSet(object, &set);
  818.         
  819.         if( set == NULL ) {
  820.             set = Q3Set_New();
  821.             if( set == NULL ) {
  822.                 status = kQ3Failure;
  823.                 goto cleanExit;
  824.             }
  825.             Q3Shape_SetSet(object, set);
  826.         }
  827.     }
  828.     
  829.     if( set ) {        
  830.         if( Q3Set_Add(set, kElementTypeW3Anchor, &W3Anchor) == kQ3Failure ) {
  831.             status = kQ3Failure;
  832.             goto cleanExit;
  833.         }
  834.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  835.         if( Q3AttributeSet_Add(object, kElementTypeW3Anchor, &W3Anchor) == kQ3Failure ) {
  836.             status = kQ3Failure;
  837.             goto cleanExit;
  838.         }
  839.     } else 
  840.         status = kQ3Failure;
  841.         
  842. cleanExit:
  843.     if( set )
  844.         Q3Object_Dispose(set);
  845.     if( string )
  846.         Q3Object_Dispose(string);
  847.     return status;
  848. }
  849.  
  850. TQ3Boolean W3Anchor_GetFromObject(TQ3Object object, W3AnchorData *data)
  851. {
  852.     TQ3SetObject    set;
  853.     TQ3Boolean        result;
  854.     
  855.     W3Anchor_Empty(data);
  856.     data->url = NULL;
  857.     data->description = NULL;
  858.     set = NULL;
  859.  
  860.     /* The object passed in must be a shape or a geometry. */
  861.     if (Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True) {
  862.         Q3Geometry_GetAttributeSet(object, &set);
  863.         if (set != NULL) {
  864.             result = W3Anchor_GetFromSet(set, data);
  865.             Q3Object_Dispose(set);
  866.             if (result == kQ3True)
  867.                 return result;
  868.             set = NULL;
  869.         }
  870.     }
  871.     if (Q3Object_IsType(object, kQ3SharedTypeShape) == kQ3True) {
  872.         Q3Shape_GetSet(object, &set);
  873.         if (set != NULL) {
  874.             result = W3Anchor_GetFromSet(set, data);
  875.             Q3Object_Dispose(set);
  876.             return result;
  877.         }
  878.     }
  879.     return kQ3False;
  880. }
  881.  
  882. TQ3Boolean W3Anchor_GetFromSet(TQ3SetObject set, W3AnchorData *data)
  883. {
  884.     TQ3Object            unkObj;
  885.     TQ3Boolean            result;
  886.     TQ3GroupPosition    position;
  887.  
  888.     result = kQ3False;
  889.  
  890.     /* Ideally, you'll find one of these. */
  891.     if (Q3Set_Contains(set, kElementTypeW3Anchor) == kQ3True) {
  892.         if (Q3Set_Get(set, kElementTypeW3Anchor, data) == kQ3Failure)
  893.             return kQ3False;    /* Error: Contains, but can't get! */
  894.         return kQ3True;
  895.     }
  896.  
  897.     /* But due to a bug in QuickDraw 3D versions prior to 1.0.4, the
  898.         element may be contained within another set in the unknown 
  899.         element. */
  900.     if (Q3Set_Contains(set, kQ3ElementTypeUnknown) == kQ3True) {
  901.         if (Q3Set_Get(set, kQ3ElementTypeUnknown, &unkObj) == kQ3Failure)
  902.             return kQ3False;    /* Error: Contains, but can't get! */
  903.         if (unkObj == NULL)
  904.             return kQ3False;
  905.         /* Unknown objects may contain one object or a group. */
  906.         if (Q3Object_IsType(unkObj, kQ3SharedTypeSet) == kQ3True)
  907.             result = W3Anchor_GetFromSet(unkObj, data);
  908.         else if (Q3Object_IsType(unkObj, kQ3ShapeTypeGroup) == kQ3True) {
  909.             Q3Group_GetFirstPositionOfType(unkObj, kQ3SharedTypeSet,
  910.                 &position);
  911.             if (position != NULL) {
  912.                 Q3Group_GetPositionObject(unkObj, position, &set);
  913.                 result = W3Anchor_GetFromSet(set, data);
  914.             }
  915.         }
  916.         Q3Object_Dispose(unkObj);
  917.     }
  918.     return result;
  919. }
  920.  
  921.  
  922. TQ3Boolean W3Anchor_GetFromHitData(
  923.     const TQ3HitData *hitData, 
  924.     W3AnchorData *data)
  925. {
  926.     if (data == NULL)
  927.         return kQ3False;
  928.         
  929.     return W3Anchor_GetFromObject (hitData->object, data);
  930. }
  931.  
  932. #ifdef __cplusplus
  933. extern "C" {
  934. #endif  /* __cplusplus */
  935.  
  936. TQ3Status W3Anchor_Traverse(
  937.     TQ3Object                unused,
  938.     W3AnchorData            *URLdata,
  939.     TQ3ViewObject            view);
  940.  
  941. #ifdef __cplusplus
  942. }
  943. #endif    /* __cplusplus */
  944.  
  945. /*
  946.  * W3Anchor_Traverse
  947.  */
  948. TQ3Status W3Anchor_Traverse(
  949.     TQ3Object                unused,
  950.     W3AnchorData            *URLdata,
  951.     TQ3ViewObject            view)
  952. {
  953.     TQ3Size        size;
  954.  
  955.     (void) unused;
  956.     
  957.     if (URLdata->url == NULL)
  958.         return kQ3Success;
  959.     
  960.     size = Q3Size_Pad(strlen(URLdata->url) + 1);
  961.     size += sizeof(TQ3Uns32);
  962.     
  963.     if( Q3View_SubmitWriteData(view, size, URLdata, NULL) == kQ3Failure )
  964.         return kQ3Failure;
  965.     
  966.     if(URLdata->description) {
  967.         if( Q3Object_Submit(URLdata->description, view) == kQ3Failure )
  968.             return kQ3Failure;
  969.     }
  970.     
  971.     return kQ3Success;
  972. }
  973.  
  974. /*
  975.  * W3Anchor_Write
  976.  */
  977. static TQ3Status W3Anchor_Write(
  978.     W3AnchorData            *URLdata,
  979.     TQ3FileObject            file)
  980. {
  981.     return 
  982.         Q3String_Write(URLdata->url, file) == kQ3Success &&
  983.         Q3Uns32_Write((unsigned long) URLdata->options, file) == kQ3Success ? kQ3Success : kQ3Failure;
  984. }
  985.  
  986. /*
  987.  * W3Anchor_ReadData
  988.  */
  989. static TQ3Status W3Anchor_ReadData(
  990.     TQ3SetObject            set,
  991.     TQ3FileObject            file)
  992. {
  993.     char                buf[kQ3StringMaximumLength];
  994.     W3AnchorData        URLData = {NULL, NULL, kW3AnchorOptionNone};
  995.     
  996.     if (Q3String_Read(buf, NULL, file) == kQ3Failure)
  997.         return kQ3Failure;
  998.  
  999.     URLData.url = (char *) malloc( strlen(buf) + 1);
  1000.     strcpy( URLData.url, buf);
  1001.     
  1002.     if (Q3Uns32_Read( (unsigned long *) &URLData.options, file) == kQ3Failure)
  1003.         return kQ3Failure;
  1004.     
  1005.     if( Q3File_IsEndOfContainer(file, NULL) == kQ3False ) {
  1006.         URLData.description = Q3File_ReadObject(file);
  1007.     }
  1008.     
  1009.     return Q3Set_Add(set, kElementTypeW3Anchor, &URLData);
  1010. }
  1011.  
  1012. /*
  1013.  * W3Anchor_CopyAdd
  1014.  */
  1015. static TQ3Status W3Anchor_CopyAdd(
  1016.     W3AnchorData    *src,
  1017.     W3AnchorData    *dst)
  1018. {
  1019.     long    i;
  1020.     
  1021.     if (src->url == NULL)
  1022.         return kQ3Failure;
  1023.  
  1024.     i = strlen(src->url);
  1025.     
  1026.     if (i == 0)
  1027.         return kQ3Failure;
  1028.     
  1029.     dst->url = (char *) malloc(i + 1);
  1030.     
  1031.     if (dst->url == NULL)
  1032.         return kQ3Failure;
  1033.         
  1034.     strcpy(dst->url, src->url);
  1035.     
  1036.     if( src->description ) {
  1037.         TQ3StringObject    stringReference;
  1038.         
  1039.         stringReference = Q3Shared_GetReference(src->description);
  1040.         
  1041.         if( stringReference == NULL) {
  1042.             return kQ3Failure;
  1043.         }
  1044.         
  1045.         dst->description = stringReference;
  1046.     } else
  1047.         dst->description = NULL;
  1048.         
  1049.     dst->options = src->options;
  1050.     return kQ3Success;
  1051. }
  1052.  
  1053. /*
  1054.  * W3Anchor_CopyReplace
  1055.  */
  1056. static TQ3Status W3Anchor_CopyReplace(
  1057.     W3AnchorData    *src,
  1058.     W3AnchorData    *dst)
  1059. {
  1060.     long    i;
  1061.     char    *c;
  1062.     
  1063.     if (src->url == NULL)
  1064.         return kQ3Failure;
  1065.  
  1066.     i = strlen(src->url);
  1067.     
  1068.     if (i == 0)
  1069.         return kQ3Failure;
  1070.         
  1071.     c = (char *) realloc(dst->url, i + 1);
  1072.     
  1073.     if (c == NULL)
  1074.         return kQ3Failure;
  1075.     
  1076.     dst->url = c;
  1077.         
  1078.     strcpy(dst->url, src->url);
  1079.     
  1080.     if( src->description ) {
  1081.         TQ3StringObject    stringReference;
  1082.         
  1083.         stringReference = Q3Shared_GetReference(src->description);
  1084.         
  1085.         if( stringReference == NULL) {
  1086.             return kQ3Failure;
  1087.         }
  1088.         
  1089.         if( dst->description ) {
  1090.             Q3Object_Dispose(dst->description);
  1091.         }
  1092.         
  1093.         dst->description = stringReference;
  1094.     } else
  1095.         dst->description = NULL;
  1096.         
  1097.     dst->options = src->options;
  1098.     return kQ3Success;
  1099. }
  1100.  
  1101. /*
  1102.  * W3Anchor_Delete
  1103.  */
  1104. static TQ3Status W3Anchor_Delete(
  1105.     W3AnchorData    *URLData)
  1106. {
  1107.     if (URLData->url != NULL) 
  1108.     {
  1109.         free(URLData->url);
  1110.         URLData->url = NULL;
  1111.     }
  1112.     if (URLData->description != NULL)
  1113.     {
  1114.         Q3Object_Dispose(URLData->description);
  1115.         URLData->description = NULL;
  1116.     }
  1117.  
  1118.     return kQ3Success;
  1119. }
  1120.  
  1121. /*
  1122.  * W3Anchor_MetaHandler
  1123.  */
  1124. static TQ3FunctionPointer W3Anchor_MetaHandler(
  1125.     TQ3MethodType        methodType)
  1126. {
  1127.     switch (methodType)
  1128.     {
  1129.         case kQ3MethodTypeObjectTraverse:
  1130.             return (TQ3FunctionPointer) W3Anchor_Traverse;
  1131.         case kQ3MethodTypeObjectWrite:
  1132.             return (TQ3FunctionPointer) W3Anchor_Write;
  1133.         case kQ3MethodTypeObjectReadData:
  1134.             return (TQ3FunctionPointer) W3Anchor_ReadData;
  1135.         case kQ3MethodTypeElementCopyAdd:
  1136.         case kQ3MethodTypeElementCopyGet:
  1137.         case kQ3MethodTypeElementCopyDuplicate:
  1138.             return (TQ3FunctionPointer) W3Anchor_CopyAdd;
  1139.         case kQ3MethodTypeElementCopyReplace:
  1140.             return (TQ3FunctionPointer) W3Anchor_CopyReplace;
  1141.         case kQ3MethodTypeElementDelete:
  1142.             return (TQ3FunctionPointer) W3Anchor_Delete;
  1143.         default:
  1144.             return (TQ3FunctionPointer) NULL;
  1145.     }
  1146. }
  1147.  
  1148. /*
  1149.  * W3Anchor_Register
  1150.  */
  1151. TQ3Status W3Anchor_Register(
  1152.     void)
  1153. {
  1154.     gW3AnchorClass = 
  1155.         Q3ElementClass_Register(
  1156.             kElementTypeW3Anchor,
  1157.             "W3Anchor",
  1158.             sizeof(W3AnchorData),
  1159.             W3Anchor_MetaHandler);
  1160.  
  1161.     return (gW3AnchorClass == NULL ? kQ3Failure : kQ3Success);
  1162. }
  1163.  
  1164. TQ3Status W3Anchor_Unregister(
  1165.     void)
  1166. {
  1167.     if(gW3AnchorClass)
  1168.         return Q3ObjectClass_Unregister(gW3AnchorClass);
  1169.     else
  1170.         return kQ3Success;
  1171. }
  1172.  
  1173. void W3Anchor_Empty (
  1174.     W3AnchorData *URLData)
  1175. {
  1176.     if (URLData != NULL)
  1177.         W3Anchor_Delete (URLData);
  1178. }
  1179.  
  1180.  
  1181. /***********************************************************************************************
  1182. *
  1183. *    W3Inline - Attach this to a proxy group or geometry
  1184. *
  1185. *
  1186. ***********************************************************************************************/
  1187.  
  1188. /*
  1189.  * Utility function to add a name on a group object, geometry object, or attribute set
  1190.  */
  1191.  
  1192. TQ3Status    SetW3Inline(TQ3Object object, char *url)
  1193. {
  1194.     TQ3AttributeSet        set = NULL;
  1195.     TQ3Status            status = kQ3Success;
  1196.     W3InlineData        W3Inline;
  1197.     
  1198.     W3Inline.url = url;
  1199.  
  1200.     if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  1201.         Q3Geometry_GetAttributeSet(object, &set);
  1202.         
  1203.         if( set == NULL ) {
  1204.             set = Q3AttributeSet_New();
  1205.             if( set == NULL ) {
  1206.                 status = kQ3Failure;
  1207.                 goto cleanExit;
  1208.             }
  1209.             Q3Geometry_SetAttributeSet(object, set);
  1210.         }
  1211.     } else     if( Q3Object_IsType(object, kQ3ShapeTypeGroup ) == kQ3True ) {
  1212.         Q3Shape_GetSet(object, &set);
  1213.         
  1214.         if( set == NULL ) {
  1215.             set = Q3Set_New();
  1216.             if( set == NULL ) {
  1217.                 status = kQ3Failure;
  1218.                 goto cleanExit;
  1219.             }
  1220.             Q3Shape_SetSet(object, set);
  1221.         }
  1222.     }
  1223.         
  1224.     if( set ) {    
  1225.         if( Q3Set_Add(set, kElementTypeW3Inline, &W3Inline) == kQ3Failure ) {
  1226.             status = kQ3Failure;
  1227.             goto cleanExit;
  1228.         }
  1229.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  1230.         if( Q3AttributeSet_Add(object, kElementTypeW3Inline, &W3Inline) == kQ3Failure ) {
  1231.             status = kQ3Failure;
  1232.             goto cleanExit;
  1233.         }
  1234.     } else 
  1235.         status = kQ3Failure;
  1236.         
  1237. cleanExit:
  1238.     if( set )
  1239.         Q3Object_Dispose(set);
  1240.     return status;
  1241. }
  1242.  
  1243. /*
  1244.  * Static Functions
  1245.  */
  1246. static TQ3Status W3Inline_Traverse(
  1247.     TQ3Object                unused,
  1248.     W3InlineData            *inlineData,
  1249.     TQ3ViewObject            view)
  1250. {
  1251.     TQ3Size        size;
  1252.     
  1253.     (void) unused;
  1254.  
  1255.     if (inlineData->url == NULL)
  1256.         return kQ3Success;
  1257.     
  1258.     size = Q3Size_Pad(strlen(inlineData->url) + 1);
  1259.     
  1260.     return
  1261.         Q3View_SubmitWriteData(view, size, inlineData, NULL);
  1262. }
  1263.  
  1264. static TQ3Status W3Inline_Write(
  1265.     W3InlineData            *inlineData,
  1266.     TQ3FileObject            file)
  1267. {
  1268.     return 
  1269.         Q3String_Write(inlineData->url, file) == kQ3Success &&
  1270.         Q3Comment_Write("url", file) == kQ3Success ? kQ3Success : kQ3Failure;
  1271. }
  1272.  
  1273. static TQ3Status W3Inline_ReadData(
  1274.     TQ3SetObject            set,
  1275.     TQ3FileObject            file)
  1276. {
  1277.     char                buf[kQ3StringMaximumLength];
  1278.     W3InlineData        inlineData;
  1279.     
  1280.     if (Q3String_Read(buf, NULL, file) == kQ3Failure)
  1281.         return kQ3Failure;
  1282.  
  1283.     inlineData.url = buf;
  1284.     
  1285.     return Q3Set_Add(set, kElementTypeW3Inline, &inlineData);
  1286. }
  1287.  
  1288. static TQ3Status W3Inline_CopyAdd(
  1289.     W3InlineData    *src,
  1290.     W3InlineData    *dst)
  1291. {
  1292.     long    i;
  1293.     
  1294.     if (src->url == NULL)
  1295.         return kQ3Failure;
  1296.  
  1297.     i = strlen(src->url);
  1298.     
  1299.     if (i == 0)
  1300.         return kQ3Failure;
  1301.         
  1302.     dst->url = (char *) malloc(i + 1);
  1303.     
  1304.     if (dst->url == NULL)
  1305.         return kQ3Failure;
  1306.         
  1307.     strcpy(dst->url, src->url);
  1308.     
  1309.     return kQ3Success;
  1310. }
  1311.  
  1312. static TQ3Status W3Inline_CopyReplace(
  1313.     W3InlineData    *src,
  1314.     W3InlineData    *dst)
  1315. {
  1316.     long    i;
  1317.     char    *c;
  1318.     
  1319.     if (src->url == NULL)
  1320.         return kQ3Failure;
  1321.  
  1322.     i = strlen(src->url);
  1323.     
  1324.     if (i == 0)
  1325.         return kQ3Failure;
  1326.         
  1327.     c = (char *) realloc(dst->url, i + 1);
  1328.     
  1329.     if (c == NULL)
  1330.         return kQ3Failure;
  1331.     
  1332.     dst->url = c;
  1333.         
  1334.     strcpy(dst->url, src->url);
  1335.     
  1336.     return kQ3Success;
  1337. }
  1338.  
  1339. static TQ3Status W3Inline_Delete(
  1340.     W3InlineData    *src)
  1341. {
  1342.     if (src->url != NULL) 
  1343.         free(src->url);
  1344.  
  1345.     return kQ3Success;
  1346. }
  1347.  
  1348. /*
  1349.  * W3Inline_MetaHandler
  1350.  */
  1351. static TQ3FunctionPointer W3Inline_MetaHandler(
  1352.     TQ3MethodType        methodType)
  1353. {
  1354.     switch (methodType)
  1355.     {
  1356.         case kQ3MethodTypeObjectTraverse:
  1357.             return (TQ3FunctionPointer) W3Inline_Traverse;
  1358.         case kQ3MethodTypeObjectWrite:
  1359.             return (TQ3FunctionPointer) W3Inline_Write;
  1360.         case kQ3MethodTypeObjectReadData:
  1361.             return (TQ3FunctionPointer) W3Inline_ReadData;
  1362.         case kQ3MethodTypeElementCopyAdd:
  1363.         case kQ3MethodTypeElementCopyGet:
  1364.         case kQ3MethodTypeElementCopyDuplicate:
  1365.             return (TQ3FunctionPointer) W3Inline_CopyAdd;
  1366.         case kQ3MethodTypeElementCopyReplace:
  1367.             return (TQ3FunctionPointer) W3Inline_CopyReplace;
  1368.         case kQ3MethodTypeElementDelete:
  1369.             return (TQ3FunctionPointer) W3Inline_Delete;
  1370.         default:
  1371.             return (TQ3FunctionPointer) NULL;
  1372.     }
  1373. }
  1374.  
  1375. /*
  1376.  * W3Inline_Register
  1377.  */
  1378. TQ3Status W3Inline_Register(
  1379.     void)
  1380. {
  1381.     gW3InlineClass = 
  1382.         Q3ElementClass_Register(
  1383.             kElementTypeW3Inline,
  1384.             "W3Inline",
  1385.             sizeof(W3InlineData),
  1386.             W3Inline_MetaHandler);
  1387.  
  1388.     return (gW3InlineClass == NULL ? kQ3Failure : kQ3Success);
  1389. }
  1390.  
  1391. TQ3Status W3Inline_Unregister(
  1392.     void)
  1393. {
  1394.     return Q3ObjectClass_Unregister(gW3InlineClass);
  1395. }
  1396.  
  1397.  
  1398. /***********************************************************************************************
  1399. *
  1400. *    This one is obsolete.  The code below will convert to the new type on reading and writing
  1401. *
  1402. *
  1403. ***********************************************************************************************/
  1404.  
  1405. /*
  1406.  * Static Functions
  1407.  */
  1408. static TQ3Status WWWAnchor_Traverse(
  1409.     TQ3Object                unused,
  1410.     WWWAnchorData            *wwwdata,
  1411.     TQ3ViewObject            view)
  1412. {
  1413.     TQ3Size        size;
  1414.  
  1415.     (void)unused;
  1416.     if (wwwdata->url == NULL)
  1417.         return kQ3Success;
  1418.     
  1419.     size = Q3Size_Pad(strlen(wwwdata->url) + 1);
  1420.     
  1421.     return
  1422.         Q3View_SubmitWriteData(view, size, wwwdata, NULL);
  1423. }
  1424.  
  1425. static TQ3Status WWWAnchor_Write(
  1426.     WWWAnchorData            *wwwdata,
  1427.     TQ3FileObject            file)
  1428. {
  1429.     return 
  1430.         Q3String_Write(wwwdata->url, file) == kQ3Success &&
  1431.         Q3Comment_Write("url", file) == kQ3Success ? kQ3Success : kQ3Failure;
  1432. }
  1433.  
  1434. static TQ3Status WWWAnchor_ReadData(
  1435.     TQ3SetObject            set,
  1436.     TQ3FileObject            file)
  1437. {
  1438.     char                buf[kQ3StringMaximumLength];
  1439.     WWWAnchorData        wwwdata;
  1440.     W3AnchorData        W3Anchor;
  1441.     
  1442.     if (Q3String_Read(buf, NULL, file) == kQ3Failure)
  1443.         return kQ3Failure;
  1444.  
  1445.     wwwdata.url = (char *) malloc(strlen(buf) + 1);
  1446.     strcpy(wwwdata.url, buf);
  1447.  
  1448.     W3Anchor.url = (char *) malloc(strlen(buf) + 1);
  1449.     strcpy(W3Anchor.url, buf);
  1450.      
  1451.      W3Anchor.description = NULL;
  1452.      W3Anchor.options = kW3AnchorOptionNone;
  1453.      
  1454.      Q3Set_Add(set, kElementTypeW3Anchor, &W3Anchor);
  1455.      
  1456.     return Q3Set_Add(set, kElementTypeWWWAnchor, &wwwdata);
  1457. }
  1458.  
  1459. static TQ3Status WWWAnchor_CopyAdd(
  1460.     WWWAnchorData    *src,
  1461.     WWWAnchorData    *dst)
  1462. {
  1463.     long    i;
  1464.     
  1465.     if (src->url == NULL)
  1466.         return kQ3Failure;
  1467.  
  1468.     i = strlen(src->url);
  1469.     
  1470.     if (i == 0)
  1471.         return kQ3Failure;
  1472.         
  1473.     dst->url = (char *) malloc(i + 1);
  1474.     
  1475.     if (dst->url == NULL)
  1476.         return kQ3Failure;
  1477.         
  1478.     strcpy(dst->url, src->url);
  1479.     
  1480.     return kQ3Success;
  1481. }
  1482.  
  1483. static TQ3Status WWWAnchor_CopyReplace(
  1484.     WWWAnchorData    *src,
  1485.     WWWAnchorData    *dst)
  1486. {
  1487.     long    i;
  1488.     char    *c;
  1489.     
  1490.     if (src->url == NULL)
  1491.         return kQ3Failure;
  1492.  
  1493.     i = strlen(src->url);
  1494.     
  1495.     if (i == 0)
  1496.         return kQ3Failure;
  1497.         
  1498.     c = (char *) realloc(dst->url, i + 1);
  1499.     
  1500.     if (c == NULL)
  1501.         return kQ3Failure;
  1502.     
  1503.     dst->url = c;
  1504.         
  1505.     strcpy(dst->url, src->url);
  1506.     
  1507.     return kQ3Success;
  1508. }
  1509.  
  1510. static TQ3Status WWWAnchor_Delete(
  1511.     WWWAnchorData    *src)
  1512. {
  1513.     if (src->url != NULL) 
  1514.         free(src->url);
  1515.  
  1516.     return kQ3Success;
  1517. }
  1518.  
  1519. /*
  1520.  * WWWAnchor_MetaHandler
  1521.  */
  1522. static TQ3FunctionPointer WWWAnchor_MetaHandler(
  1523.     TQ3MethodType        methodType)
  1524. {
  1525.     switch (methodType)
  1526.     {
  1527.         case kQ3MethodTypeObjectTraverse:
  1528.             return (TQ3FunctionPointer) WWWAnchor_Traverse;
  1529.         case kQ3MethodTypeObjectWrite:
  1530.             return (TQ3FunctionPointer) WWWAnchor_Write;
  1531.         case kQ3MethodTypeObjectReadData:
  1532.             return (TQ3FunctionPointer) WWWAnchor_ReadData;
  1533.         case kQ3MethodTypeElementCopyAdd:
  1534.         case kQ3MethodTypeElementCopyGet:
  1535.         case kQ3MethodTypeElementCopyDuplicate:
  1536.             return (TQ3FunctionPointer) WWWAnchor_CopyAdd;
  1537.         case kQ3MethodTypeElementCopyReplace:
  1538.             return (TQ3FunctionPointer) WWWAnchor_CopyReplace;
  1539.         case kQ3MethodTypeElementDelete:
  1540.             return (TQ3FunctionPointer) WWWAnchor_Delete;
  1541.         default:
  1542.             return (TQ3FunctionPointer) NULL;
  1543.     }
  1544. }
  1545.  
  1546. /*
  1547.  * WWWAnchor_Register
  1548.  */
  1549. TQ3Status WWWAnchor_Register(
  1550.     void)
  1551. {
  1552.     gWWWAnchorClass = 
  1553.         Q3ElementClass_Register(
  1554.             kElementTypeWWWAnchor,
  1555.             kElementNameWWWAnchor,
  1556.             sizeof(WWWAnchorData),
  1557.             WWWAnchor_MetaHandler);
  1558.  
  1559.     return (gWWWAnchorClass == NULL ? kQ3Failure : kQ3Success);
  1560. }
  1561.  
  1562. TQ3Status WWWAnchor_Unregister(
  1563.     void)
  1564. {
  1565.     return Q3ObjectClass_Unregister(gWWWAnchorClass);
  1566. }
  1567.